mod serde_plan_set;

use super::{ID, Plan, PlanSet, Tag};
use std::{
    collections::BTreeMap,
    fs::File,
    io::Write,
    mem::ManuallyDrop,
    ops::{Deref, DerefMut},
    sync::{Arc, RwLock},
};

impl Deref for PlanSet {
    type Target = BTreeMap<ID, Arc<RwLock<Plan>>>;
    fn deref(&self) -> &Self::Target {
        &self.set
    }
}

impl DerefMut for PlanSet {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.set
    }
}

impl PlanSet {
    //只允许存在一个PlanSet
    pub fn new() -> Option<Self> {
        static ONCE: std::sync::Once = std::sync::Once::new();
        let mut ret = None;
        ONCE.call_once(|| ret = Some(Self::new_impl()));
        ret
    }
    fn new_impl() -> Self {
        Self::open_old().unwrap_or_else(Self::create_new)
    }
    fn open_old() -> Option<Self> {
        if let Ok(file) = File::open("plans.ron") {
            let reader = std::io::BufReader::new(file);
            let plans: PlanSet = ron::de::from_reader(reader).unwrap();
            Some(plans)
        } else {
            None
        }
    }
    fn create_new() -> Self {
        let root = Arc::new(RwLock::new(Plan::new_root()));
        let mut set = BTreeMap::new();
        set.insert(0, root.clone());
        Self {
            set: ManuallyDrop::new(set),
            root: ManuallyDrop::new(root),
            max_id: 0,
        }
    }
    pub fn create_new_plan(&mut self, current_plan: &Arc<RwLock<Plan>>) -> Arc<RwLock<Plan>> {
        self.max_id += 1;
        let new_plan = Plan::create_empty(current_plan, self.max_id);
        self.set.insert(self.max_id, new_plan.clone());
        new_plan
    }
    pub fn search(&self, tags: &[Tag]) -> Vec<Arc<RwLock<Plan>>> {
        self.set
            .values()
            .filter_map(|plan| {
                let plan_reader = plan.read().unwrap();
                tags.iter()
                    .all(|tag| plan_reader.tags.contains(tag))
                    .then_some(plan.clone())
            })
            .collect()
    }
}

impl Drop for PlanSet {
    fn drop(&mut self) {
        let mut writer = std::io::BufWriter::new(File::create("plans.ron").unwrap());
        let data = ron::to_string(self).unwrap();
        writer.write_all(data.as_bytes()).unwrap();
        unsafe {
            crate::ui::SEARCH_RESULT.lock().unwrap().clear();
            ManuallyDrop::drop(&mut self.set);
            ManuallyDrop::drop(&mut self.root);
        }
    }
}
